home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 May / EnigmA AMIGA RUN 18 (1997)(G.R. Edizioni)(IT)[!][issue 1997-05][EAR-CD II].iso / softwareupdate / system / amigados / introduction / introduction.doc < prev    next >
Text File  |  1996-10-10  |  28KB  |  812 lines

  1. 1    AMIGADOS
  2.  
  3. 1.1  INTRODUCTION
  4.  
  5. Welcome to the AmigaDOS C manual. This manual is a part of a
  6. series of C manuals which describe how to write programs for
  7. the Amiga. The complete collection is called the Amiga C
  8. Encyclopedia. All documents, examples and illustrations are
  9. made by Anders Bjerin.
  10.  
  11. This manual consists of eight chapters which each will describe
  12. a specific topic on how to control AmigaDOS with C. The
  13. chapters are:
  14.  
  15.   1. AmigaDOS
  16.   
  17.   This chapter you are currently reading. Gives a short
  18.   introduction to AmigaDOS. It explains some commonly used words
  19.   and describes how AmigaDOS works. You need this information
  20.   before you can continue with the following chapters.
  21.  
  22.  
  23.   2. Files
  24.   
  25.   Explains how to work with files. Describes how open files,
  26.   read as well as save data, and finally close the file again.
  27.   In this chapter you will also find information on how to
  28.   work with files in a multitasking environment.
  29.  
  30.  
  31.   3. File Functions
  32.  
  33.   Describes some extra useful functions you might want to use
  34.   when you are working with files. Teaches how to create
  35.   directories, how to delete, rename, as well as alter the
  36.   protection flags of both files and directories, and finally
  37.   how to attach comments to files.
  38.  
  39.  
  40.   4. Buffered IO
  41.  
  42.   Explains the new buffered input and output routines which
  43.   were introduced in Release 2. Very handy functions when you
  44.   need to read or write a lot of small blocks of data but still
  45.   want to keep the speed up.
  46.  
  47.  
  48.   5. Parsing Command Line
  49.  
  50.   This chapter will also describe some new routines which were
  51.   included in Release 2. These new routines take care of the
  52.   problems on how to parse, collect and interpret arguments
  53.   from the command line.
  54.  
  55.  
  56.   6. Handlers
  57.  
  58.   In this chapter you will learn about the different handlers
  59.   AmigaDOS is using. Work with console windows, send text to
  60.   printers, use the built in speech synthesizer, work with the
  61.   parallel or serial port, and send data between different
  62.   programs can all easily be done with the same functions
  63.   described in this chapter.
  64.  
  65.  
  66.   7. Advanced AmigaDOS Routines
  67.  
  68.   This chapter will describe some advanced features in
  69.   AmigaDOS. It explains how to examine directories and look for
  70.   files, how to get information from special devices, and how
  71.   to work with the low level routines in AmigaDOS.
  72.  
  73.   8. Miscellaneous
  74.  
  75.   The last chapter in this manual describes some goodies in
  76.   AmigaDOS that might be useful.
  77.  
  78.  
  79.  
  80. 1.2  COMMONLY USED AMIGADOS WORDS
  81.  
  82. Before you can continue with the other chapters you need to
  83. know the meaning of some commonly used words, and how AmigaDOS
  84. work. For more information about AmigaDOS and the Shell see the
  85. manuals which were included with your computer when you bought
  86. it.
  87.  
  88.  
  89.  
  90. 1.2.1  PHYSICAL DEVICES
  91.  
  92. Physical devices are parts of the Amiga to which data can
  93. either be sent to, read from or both. The most commonly used
  94. physical device is undoubtedly the internal disk drive "DF0:",
  95. but there exist a lot of other physical devices.
  96.  
  97.   Here is the list of the standard AmigaDOS physical devices:
  98.   -------------------------------------------------------------
  99.   DF0:   File IO on disk drive 0
  100.   DF1:   File IO on disk drive 0
  101.   DF2:   File IO on disk drive 0 
  102.   DF3:   File IO on disk drive 0 
  103.  
  104.   RAM:   File IO on RAM disk
  105.   DHx:   File IO on hard drive x (DH0, DH1, DH2, and so on...) 
  106.  
  107.   SER:   Buffered serial IO
  108.   PAR:   Buffered parallel IO
  109.   PRT:   Output to printer (trough Preferences)
  110.  
  111.   CON:   Buffered translated window IO
  112.   RAW:   Unbuffered untranslated window IO 
  113.  
  114.   PIPE:  Buffered IO between programs
  115.   AUX:   Unbuffered serial IO 
  116.   SPEAK: Output to the narrator (speech) device
  117.  
  118.   NIL:   Output to nothing
  119.   -------------------------------------------------------------
  120.   (IO = Input / Output)
  121.   (Note that all device-names end with a colon)
  122.   (The listed devices are also usually called as "handlers")
  123.  
  124.  
  125. If you want to copy a file called "program.c" from the internal
  126. disk drive (DF0:) to the second disk drive (DF1:) you write:
  127.  
  128.   1.Prog:>
  129.   1.Prog:> copy from DF0:program.c to DF1:
  130.  
  131. If you want to print the file you can do it by simply copying
  132. the file to the "PRT:" device. The data in the file will be
  133. translated with help of the current settings in Preferences and
  134. outputed to the printer.
  135.  
  136.   1.Prog:> 
  137.   1.Prog:> copy from DF0:program.c to PRT:
  138.  
  139. Since AmigaDOS treats all devices equal you can even let it
  140. read your file out loud with help of the "speak" device. You
  141. only have to copy the file to the "SPEAK:" device, and the
  142. Amiga will immediately start to read the file out loud.
  143.  
  144.   1.Prog:> 
  145.   1.Prog:> copy from DF0:program.c to SPEAK:
  146.  
  147. AmigaDOS allows you also to use special windows (CON: or RAW:)
  148. for input/output. The only thing you need to add are some extra
  149. arguments just after the device name. These extra arguments
  150. tells AmigaDOS what size and position of the window you want,
  151. and if you want to use any special options. The syntax for the
  152. console window is:
  153.  
  154.   CON:x/y/width/height/title/option(s)
  155.  
  156. If you want to use spaces in the title you have to put
  157. quotation marks around the whole expression. With "Release 2"
  158. (WB2.xx) some special options where added to the "CON:" device:
  159.  
  160.   Option     Description
  161.   -------------------------------------------------------------
  162.   /AUTO:     Opens the window first when there is some IO
  163.   /BACKDROP: Should be a "backdrop" window (no other window can
  164.              be moved behind it)
  165.   /CLOSE:    Add a close window gadget
  166.   /NOBORDER: Draw no borders around the window
  167.   /NODRAG:   Remove the drag gadget
  168.   /NOSIZE:   Remove the size gadget
  169.   /SCREEN:   Open on a specified public screen "/SCREEN [name]"
  170.   /SIMPLE    The window should use "simple refresh" mode
  171.              (see Intuition manual for more information)
  172.   /SMART:    The window should use the "smart refresh" mode
  173.              (see Intuition manual for more information)
  174.   /WAIT:     Waits with closing the window until the user types
  175.              "Ctrl-\" or clicks on the close window gadget 
  176.   /WINDOW:   Use the specified window (address in hexadecimal)
  177.              "/WINDOW [pointer to window]"
  178.  
  179. To copy a file called "prg.c" from the current device to a
  180. "CON:" window you simply write:
  181.  
  182.   1.Prog:>
  183.   1.Prog:> copy prg.c to CON:10/20/320/100/Text/CLOSE/WAIT/
  184.  
  185. This will copy the data in the file to a window positioned at
  186. x position 10, y position 20, width 320, height 100, with the
  187. title "Text", and it will be closed first when you click on
  188. the close window gadget which has been added. If you want to
  189. use spaces in the title you need to put quotes around the whole
  190. expression:
  191.  
  192.   1.Prog:>
  193.   1.Prog:> copy prg.c to "CON:10/20/320/100/My Text/CLOSE/WAIT/"
  194.  
  195.  
  196. All these types of "physical devices" which have been listed
  197. are also sometimes called "handlers". The handler is actually
  198. the process behind the device, and will be fully explained in
  199. the chapter "Handlers".
  200.  
  201.  
  202.  
  203. 1.2.2  VOLUMES
  204.  
  205. To access a disk you can either use the physical device name of
  206. the drive in which the disk is, or use the name of the disk
  207. (the "volume name"). If you want to copy a file called
  208. "program.c" from the RAM disk to a disk called "DOCUMENTS", and
  209. the disk is in the second disk drive, you can either write:
  210.  
  211.   1.Prog:>
  212.   1.Prog:> copy from RAM:program.c to DF1:
  213.  
  214. or
  215.  
  216.   1.Prog:>
  217.   1.Prog:> copy from RAM:program.c to DOCUMENTS:
  218.  
  219. (Note the colon after the volume name!) The advantage with the
  220. last example is that you do not need to bother about which
  221. drive the DOCUMENTS disk is in. Furthermore, if the desired
  222. disk was not in any drive, AmigaDOS will ask you to insert it,
  223. and you do not need to worry about writing to the wrong disk.
  224.  
  225.  
  226.  
  227. 1.2.3  DIRECTORIES/SUBDIRECTORIES/FILES
  228.  
  229. On a disk there may exist directories, subdirectories and files.
  230. A subdirectory is a directory inside another directory. (There
  231. may be subdirectories inside other subdirectories and so on...)
  232. (See picture "DirectorySubdirectoriesFiles.pic")
  233.  
  234.                       DEVICE/VOLUME
  235.                             |
  236.       /---------------------+---------------------\
  237.       |                     |                     |
  238.     FILES               DIRECTORY             DIRECTORY
  239.                             |                     |
  240.                           FILES             SUBDIRECTORIES
  241.                                                   |
  242.                                                 FILES
  243.  
  244.  
  245. If you want to access a file which is in the "current
  246. directory" (the directory you are currently standing in) you
  247. only have to use the file name.
  248.  
  249.   "file name"
  250.  
  251. If you want to access a file which is in a directory further
  252. in you have to add the directory name, a slash (/) and then
  253. the file name. If the file is several directories in you
  254. have to add the name of each directory and a slash for every
  255. directory (subdirectory).
  256.  
  257.   "directory name"/"file name"
  258.   "directory name"/"subdirectory name"/"file name"
  259.   and so on...
  260.  
  261. If you are standing in a directory and want to access a file
  262. which is outside (one step back) you have to put a slash in
  263. front of the file name. If the file is several directories back
  264. you have to add a slash for every directory.  
  265.  
  266.   /"file name"
  267.   //"file name"
  268.   ///"file name"
  269.   and so on...
  270.  
  271. If you want to access a file on a specific device or volume you
  272. simply add the volume name, a colon (:) and then the file name.
  273. If the file is inside a directory on that volume you also have
  274. to add the directory name(s) as explained before.
  275.  
  276.   "volume name":"file name"
  277.   "volume name":"directory name"/"file name"
  278.   "volume name":"directory name"/"sub directory name"/"file name"
  279.   and so on...
  280.  
  281.  
  282.  
  283. 1.2.4  LOGICAL DEVICES
  284.  
  285. Logical devices is a simple way to find files, regardless of
  286. where the file actually is. For example: If you have all your
  287. C programs on a disk called "Programs", placed in directory
  288. named "Examples", and you want to run the program "test1" you
  289. need to write: ("volume name":"directory name"/"file name")
  290.  
  291.   1.Prog:>
  292.   1.Prog:> Programs:Examples/test1
  293.  
  294. If you often want to access files in that directory you can
  295. assign a "logical device" to it. You then only need to write
  296. the logical device name and the file name, and AmigaDOS will
  297. automatically look on the right disk and directory.
  298.  
  299. You assign logical devices by using the command "Assign"
  300. which is called like this: (Note the space between the logical
  301. device name and the path.)
  302.  
  303.   Assign "logical device name": [device/(directory/subdirectory)]
  304.  
  305. For example:
  306.  
  307.   1.Prog:>
  308.   1.Prog:> Assign EX: Programs:Examples
  309.  
  310. To gain access to the file "test1" you then only need to write:
  311.  
  312.   1.Prog:>
  313.   1.Prog:> EX:test1
  314.  
  315.  
  316. When you boot up the computer it will automatically create some
  317. commonly used logical devices. A good example is the logical
  318. device "FONTS:". It is automatically assigned to the system
  319. disk's "fonts" directory. Here is the list of some of the most
  320. commonly used logical devices:
  321.  
  322.   Standard
  323.   Logical
  324.   Devices         Description
  325.   -------------------------------------------------------------
  326.   SYS:            The system disk which was used when the
  327.                   computer started ("the boot disk")
  328.   C:              All Shell (CLI) commands can be found here
  329.   FONTS:          All fonts can be found here
  330.   L:              All types of (file) handlers are stored here
  331.   LIBS:           All disk libraries can be found here
  332.                   [loaded when you call OpenLibrary().]
  333.   S:              All batch files (files with Shell commands)
  334.                   are stored here
  335.   DEVS:           All "devices" (device is a commonly used
  336.                   word...) can be found here.
  337.   and so on...
  338.   -------------------------------------------------------------
  339.  
  340. The logical device "C:" is assigned to the system disk's "c"
  341. directory, where all CLI commands are. If you have copied some
  342. CLI commands to the RAM disk, and you want AmigaDOS to look
  343. there instead of looking on the system disk's c directory you
  344. simply reassign the C: device. For example:
  345.  
  346.   1.Prog:>
  347.   1.Prog:> Assign C: RAM:
  348.  
  349.  
  350.  
  351. 1.2.5  PHYSICAL/LOGICAL DEVICES & VOLUMES
  352.  
  353. To list all physical and logical devices as well as all
  354. currently accessable volumes you can use the "Assign" command.
  355. Simply type "Assign" without any arguments, and you will see
  356. something like this:
  357.  
  358.   1.Prog:>
  359.   1.Prog:> Assign
  360.   Volumes:
  361.   Ram Disk [Mounted]
  362.   HD4 [Mounted]
  363.   HD3 [Mounted]
  364.   HD2 [Mounted]
  365.   DH1 [Mounted]
  366.   HD0 [Mounted]
  367.   
  368.   Directories:
  369.   GPFax          HD0:GPFax
  370.   CProg:         HD3:CPrograms
  371.   ACE:           HD4:AmigaCEncyclopedia
  372.   DOC:           HD2:Documents
  373.   BACKUP:        HD4:Backup
  374.   REXX           HD0:RexxPrograms
  375.   CLIPS          Ram Disk:Clipboards
  376.   T              Ram Disk:T
  377.   ENV            Ram Disk:env
  378.   ENVARC         HD0:prefs/env-archive
  379.   SYS            HD0:
  380.   C              HD0:c
  381.   S              HD0:s
  382.   LIBS           HD0:libs
  383.   DEVS           HD0:devs
  384.   FONTS          HD0:Fonts
  385.   L              HD0:l
  386.   
  387.   Devices:
  388.   PIPE AUX SPEAK RAM CON
  389.   RAW SER PAR PRT DH0
  390.   DF0 DF1 DH1 DH2 DH3
  391.  
  392.  
  393. At the top you will see all currently accessable volumes, and
  394. if they are "mounted" (in a drive) or not. Then all logical
  395. devices are listed (called "Directories"), and finally the
  396. physical devices are listed.
  397.  
  398.  
  399.  
  400. 1.3  DOS LIBRARY
  401.  
  402. Before you can access any function in a library you normally
  403. have to open it with help of the OpenLibrary() function. The
  404. AmigaDOS library is however opened automatically for you when
  405. your program is started. You do therefore not need to (nor
  406. should) open or close the dos library yourself as you do with
  407. the other libraries.
  408.  
  409. There is one thing you must look out for. Although the AmigaDOS
  410. library (the dos library as it is usually called) will have
  411. been opened for you it is not sure that you may use all the
  412. functions described in this manual. Many of the functions were
  413. first included with Release 2, and only exist in dos library
  414. version 36 or higher. If you try to use a new function on an
  415. old Amiga the system will crash!
  416.  
  417. If you use any of the new functions you must first check that
  418. the user really has the needed library version or higher.
  419. If the user does not have the needed library version your
  420. program must immediately tell the user that he/she has a too
  421. old dos library, and then immediately terminate, or at least
  422. not use the new functions.
  423.  
  424. Whenever I describe a function I will always tell you when the
  425. function was first included in the library. For example, when
  426. you see the sign "V36+" it means that the function may only be
  427. used if the user has version 36 or higher. If you see the text
  428. "All versions" it means that the function can be used with any
  429. version of that library.
  430.  
  431. Normally when you open a library you can tell the Amiga what is
  432. the lowest library version you accept. The question is now how
  433. you can check the version number of the dos library if it is
  434. already open. The answer is simple. You only have to declare
  435. the global dos library pointer as an external pointer, and it
  436. will automatically be initialized for you. The library pointer
  437. must be called "DOSBase". Here is an example: (Simply include
  438. this line at the beginning of your code, and the rest will be
  439. done automatically for you.)
  440.  
  441.   extern struct DosLibrary *DOSBase;
  442.  
  443. Once you have a pointer to the dos library you can check the
  444. current version number. The version number is found in the
  445. "lib_Version" field of the DosLibrary structure. (See header
  446. file "dos/dosextens.h" for a complete description of the
  447. DosLibrary structure.)
  448.  
  449.   /* We need dos library version 36 or higher: */
  450.   if( DOSBase->dl_lib.lib_Version < 36 )
  451.     printf( "The dos library is too old!\n" );
  452.   else
  453.     printf( "The user has the new functions in Release 2!\n" );
  454.  
  455.  
  456. Once you are sure that the user has the needed version or
  457. higher you can start to use the new functions.
  458.  
  459.   *************************************************************
  460.   *                                                           *
  461.   *  REMEMBER! If you use any function which has been marked  *
  462.   *  as a new function (V36, V37, V39, V38...) you MUST       *
  463.   *  check that the user really has the needed library        *
  464.   *  version or higher!                                       * 
  465.   *                                                           *
  466.   *************************************************************
  467.  
  468.  
  469.  
  470. 1.4  BCPL
  471.  
  472. AmigaDOS was not, as everything else on the Amiga, written in
  473. C. Instead they used the BCPL programming language which is the
  474. predecessor of C. As new dos library versions are released more
  475. and more of the old BCPL language is removed. There are however
  476. still some parts left which can not be taken away due to
  477. compatibility problems.
  478.  
  479. The reason why you need to know about this BCPL is because the
  480. language only used the data type "long word" ("LONG"). The
  481. problem is that all BCPL data must therefore be "long word
  482. aligned" - the data must start on an even word address (on
  483. a four byte boundary).
  484.  
  485. When you normally declare a structure the memory which is
  486. reserved can start on any byte address. If you would try to use
  487. such a structure together with BCPL there would be a lot of
  488. problems since BCPL would not be able to address it (use it).
  489.  
  490. See picture "LongWordAligned.pic". You can there see an
  491. illustration of a small part of the memory in the Amiga. The
  492. first byte you see has the address 0x7D00 (7D00 HEX = 32000 DEC). 
  493. This byte is located on a "long word boundary" since it can be
  494. divided by 4 (4 bytes = 1 long word). Any structure that starts
  495. on such an address can be accessed by BCPL.
  496.  
  497. Structure 1 starts on byte 0x7D00 and is therefore long word
  498. aligned and can be accessed by BCPL. However, structures 2, 3,
  499. and 4 can not be used by BCPL since they start in the middle of
  500. a long address. Structure 5 is OK since it starts on address
  501. 0x7D04 which can be divided by 4, and so on...
  502.  
  503.  
  504.  
  505. 1.4.1  LONG WORD ALIGNED STRUCTURES
  506.  
  507. To make sure that a structure really starts on a long word
  508. address (even word address = on four byte boundary) you have to
  509. allocate the memory yourself with help of AllocMem(). (Remember
  510. to deallocate the memory once you do not need it any more!)
  511.  
  512. Some new special structures with dos library version 36 or
  513. higher should be allocated with the AllocDosObject() function.
  514. These structures will also be long word aligned. When you need
  515. to use AllocDosObject() will be described in the following
  516. chapters.
  517.  
  518. Instead of writing: ("FileInfoBlock structure is a special dos
  519. structure which will be explained in the following chapters.)
  520.  
  521.   /* Declare a FileInfoBlock: (WRONG!) */
  522.   struct FileInfoBlock fib;
  523.  
  524.  
  525. You should write: (Thanks BCPL!)
  526.  
  527.   /* Declare a pointer to a FileInfoBlock structure: */
  528.   struct FileInfoBlock *my_fib_ptr;
  529.  
  530.   - - -
  531.  
  532.   /* Allocate enough memory for a FileInfoBlock structure: */
  533.   /* (OK! This memory will be long word aligned.)          */
  534.   my_fib_ptr = AllocMem( sizeof( struct FileInfoBlock ),
  535.     MEMF_ANY | MEMF_CLEAR );
  536.  
  537.   /* Check if we have allocated the memory successfully: */
  538.   if( my_fib_ptr == NULL )
  539.   {
  540.     printf( "Not enough memory!\n" );
  541.     exit( 20 );
  542.   }
  543.  
  544.   - - -
  545.   
  546.   /* Use the structure as much as you want... */
  547.  
  548.   - - -
  549.  
  550.   /* Deallocate the memory when we do not need it any more: */
  551.   FreeMem( my_fib_ptr, sizeof( struct FileInfoBlock ) );
  552.  
  553.  
  554.  
  555. 1.4.2  BCPL POINTERS (BPTR)
  556.  
  557. The pointers in the BCPL language are called "BPTR"s. Since
  558. BCPL only uses long addresses the pointers consequently only
  559. points to complete long words. The BCPL address 0x0000 is the
  560. address to the first long word in the memory. The next address
  561. is 0x0001 and it points to the second long word, and so on...
  562. When you increase a BCPL pointer by one you move 32 bits
  563. forward (32 bits = 1 long word). Anything a BPTR points to
  564. must therefore be long word aligned (start on a 32 bit
  565. address).
  566.  
  567. Normal C pointers are addressing single bytes (8 bits), and
  568. if you increase a C pointer by one you only move 8 bits
  569. foreward.
  570.  
  571. When you want to convert a BCPL pointer to a C pointer you
  572. consequently multiply the BPTR with four. (The C pointer is
  573. four times larger than the BPTR.)
  574.  
  575. When you want to convert a C pointer into a BPTR (BCPL pointer)
  576. it is a little bit trickier. To get the addresses right you
  577. simply have to divide the C pointer by four, but the pointer
  578. must also be long word aligned as all things BCPL work with.
  579. You must therefore allocate the memory for the pointer with
  580. help of AllocMem().
  581.  
  582. When you have to convert C to and from BCPL pointers you should
  583. use the special macros that are defined in header file
  584. "dos/dos.h". BADDR() converts a BPTR into a C pointer, and
  585. MKBADDR() converts a C pointer into a BPTR.
  586.  
  587. Synopsis: c_ptr = BADDR( bptr );
  588.   
  589.   c_ptr:  (APTR) The function returns a C pointer.
  590.   
  591.   bptr:   (BPTR) The BPTR (BCPL pointer) you want to convert
  592.           into a C pointer.
  593.  
  594. Synopsis: bptr = MKBADDR( c_ptr );
  595.   
  596.   bptr:   (APTR) The function returns a BPTR (BCPL pointer).
  597.  
  598.   c_ptr:  (LONG) The C pointer you want to convert into a BPTR
  599.           (BCPL pointer).
  600.           
  601.           NOTE! The address in the pointer will be correctly
  602.           converted and can be used by the dos functions.
  603.           However, if you ever have to give AmigaDOS the actual
  604.           BPTR (not the address in the pointer, but the memory
  605.           used to store the address in) it must be long word
  606.           aligned! See example 3 for more information. Luckily
  607.           this is rarely needed.
  608.           
  609.  
  610.  
  611. 1.4.3  BCPL STRINGS (BSTR)
  612.  
  613. To make life even more interesting the BCPL language uses a
  614. special type of strings called "BSTRs". A BSTR is a BCPL
  615. pointer to some data. The very first byte of that data area
  616. contains the length of the string, and the following bytes
  617. contain the actual string. Note that these BCPL strings do not
  618. terminate with a NULL sign, so you have to use the first byte
  619. in the string to get the actual length. A BSTR can therefore
  620. never be longer than 255 characters (0 - 255 = one byte). (See
  621. picture "BSTR.pic")
  622.  
  623. This BSTR gives you some problems since you can not use normal
  624. string functions like printf() together with BCPL strings. Most
  625. normal string functions expect a NULL sign at the end of the
  626. string, and since BSTRs do not have that the functions simply
  627. do not know when the string ends.
  628.  
  629. To help you I have therefore written a small function which
  630. you can include in your programs when needed. The function will
  631. copy a BCPL string into a C string which you then can use as
  632. normal. The function needs a BCPL pointer to the string that
  633. should be converted, a pointer to a normal string where the
  634. data should be inserted, and finally the maximum length of the
  635. C string.
  636.  
  637.   /* Since a BSTR never can be longer than 255 characters  */
  638.   /* we do not need a C string which is longer: (Note that */
  639.   /* we have to allocate 256 characters since the last one */
  640.   /* must be set to NULL.)                                 */
  641.   #define MAX_LENGTH 256
  642.  
  643.   - - -
  644.  
  645.   /* Declare a C string: */
  646.   UBYTE my_nice_c_string[ MAX_LENGTH ];
  647.  
  648.   - - -
  649.  
  650.   /* Convert a BSTR into a normal usable C string: */
  651.   BSTRtoC
  652.   (
  653.     my_horrible_bcpl_string,
  654.     my_nice_c_string,
  655.     MAX_LENGTH
  656.   );
  657.  
  658.   - - -
  659.  
  660.   /* Converts a BCPL string (BSTR) into a normal C string: */
  661.   void BSTRtoC
  662.   (
  663.     BSTR string_bstr, /* The BSTR (BCPL string)         */
  664.     UBYTE *string_c,  /* Pointer to a normal C string   */
  665.     int length_c      /* Maximum length of the C string */
  666.   )
  667.   {
  668.     /* Temporary string pointer: */
  669.     UBYTE *string_ptr;
  670.  
  671.     /* The length of the BSTR string: (A BSTR can not be   */
  672.     /* longer than 255 characters so we can use a unsigned */
  673.     /* byte to store the length in.)                       */
  674.     UBYTE length_bstr;
  675.  
  676.     /* The number of characters that will be copied: */
  677.     int length;
  678.  
  679.     /* Simple loop variable: */
  680.     int loop;
  681.     
  682.   
  683.     /* Since we have to put a NULL sign at the end of the  */
  684.     /* C string we can only store "length_c" - 1 number of */
  685.     /* characters. Therefore we have to reduce the length  */
  686.     /* by one:                                             */
  687.     length_c--;
  688.   
  689.     /* Convert the BSTR into a normal C pointer */
  690.     /* to a BCPL string: (Are you with me?)     */
  691.     string_ptr = (UBYTE *) BADDR( string_bstr );
  692.   
  693.     /* Get the length of the BCPL string: (A BCPL string  */
  694.     /* does not contain a NULL sign at the end, but uses  */
  695.     /* instead the first byte to tell how many characters */
  696.     /* the string contains. A BCPL string (BSTR) can      */
  697.     /* therefore not contain more than 255 characters     */
  698.     /* (0 - 255 = one byte).                              */
  699.     length_bstr = string_ptr[ 0 ];
  700.   
  701.     /* Get the smallest value: (If the C string is smallest  */
  702.     /* we should of course not copy more than can be fitted  */
  703.     /* in the C string. On the other hand, if the BCPL       */
  704.     /* string is smaller we should of course not copy more   */
  705.     /* characters than there actually exist in the BCPL      */
  706.     /* string. Consequently we should only use the smallest  */
  707.     /* value: (If you have included the header file "math.h" */
  708.     /* you can equally well use the macro "min()".)          */
  709.     length = length_c <= length_bstr ? length_c : length_bstr;
  710.  
  711.     /* Convert the BCPL string into a C string: */
  712.     for( loop = 1; loop <= length; loop++ )
  713.       string_c[ loop - 1] = string_ptr[ loop ];
  714.  
  715.     /* Note that the loop starts with 1 and not 0 as normal! */
  716.     /* The first byte in a BCPL string contains the lenght   */
  717.     /* of the string, and since we don't want to copy that   */
  718.     /* value into the C string we start one byte higher. We  */
  719.     /* must then also change the "<" sign into a "<=" since  */
  720.     /* we want to copy all characters including the last     */
  721.     /* one since that also contains a character. Normal C    */
  722.     /* strings ends with a NULL, but BSTRs do not.           */
  723.  
  724.  
  725.     /* Finally we have to put a NULL sign at the */
  726.     /* end of the C string:                      */
  727.     string_c[ loop - 1] = NULL;
  728.   }
  729.  
  730.  
  731.  
  732. 1.5  BOOLEAN VALUES USED BY AMIGADOS
  733.  
  734. Many of the functions which will be described in the following
  735. chapters return boolean values. A boolean value is a value
  736. which is either true or false, and false usualy means that the
  737. function failed to do what it was supposed to do.
  738.  
  739. Whenever you want to use a boolean varaible in normal
  740. circomstances you should declare it as "BOOL". "BOOL" is
  741. defined in header file "exec/types.h", and is actually a
  742. "short". A boolean variable should then only be given the
  743. values "TRUE" or "FALSE" which are alse defined in the same
  744. header file ("exec/types.h") as 1 and 0. 
  745.  
  746. A small demonstration on how to work with boolean values
  747. normally:
  748.  
  749.   /* Declare a boolean variable: */
  750.   BOOL my_boolean_variable;
  751.   
  752.   /* Give the boolean variable a value: */
  753.   /* (Only TRUE or FALSE may be used!)  */
  754.   my_boolean_variable = TRUE;
  755.   
  756.   /* An example on how to use it: */
  757.   if( my_boolean_variable )
  758.     printf( "True!\n" );
  759.   else
  760.     printf( "False!\n" );
  761.  
  762.  
  763. Well, this is how you work with boolean values normally.
  764. However, as life, nothing is only black and white, true or
  765. false. The boolean values used by AmigaDOS are NOT(!) of the
  766. type "short", nor is the "TRUE" value defined equally
  767. (sight...).
  768.  
  769. The boolean values used by the AmigaDOS functions are of the
  770. type "LONG" ("long"), and instead of using the normal TRUE or
  771. FALSE values you should use "DOSTRUE" and "DOSFALSE" which are
  772. defined in header file "dos/dos.h" as -1L and 0L. Note the
  773. difference between "TRUE" (defined as 1) and "DOSTRUE" (defined
  774. as -1L).
  775.  
  776. Whenever you use AmigaDOS functions which return boolean values
  777. you must store the returned value in a "LONG", and be careful
  778. to use the "DOSTRUE" and "DOSFALSE" names and not "TRUE" or
  779. "FALSE"!
  780.  
  781.   /* Simple boolean variable used by AmigaDOS: */
  782.   LONG ok;
  783.   
  784.   - - -
  785.   
  786.   /* Call some AmigaDOS function which */
  787.   /* returns a boolean value:          */
  788.   ok = SomeAmigaDOSFunction( xxx );    
  789.  
  790.   /* INCORRECT! */
  791.   if( ok == TRUE )
  792.     xxx;
  793.  
  794.   /* Correct! */
  795.   if( ok == DOSTRUE )
  796.     xxx;
  797.  
  798.   /* INCORRECT (but will work since "FALSE" */
  799.   /* and "DOSFALSE" are bot equal to 0.)    */
  800.   if( ok == FALSE )
  801.     xxx;
  802.  
  803.   /* Correct! */
  804.   if( ok == DOSFALSE )
  805.     xxx;
  806.  
  807.   /* Correct! (A simple solution to get */
  808.   /* rid of most problems...)           */
  809.   if( ok )
  810.     xxx;
  811.  
  812.